import { IXMLData } from "./IXMLData";
import { DOMParser } from "./DOMParser";
import { IXMLTag } from "./IXMLTag";
import { XMLConfig } from "./XMLConfig";
import { IXMLAttr } from "./IXMLAttr";
export class XMLParser
{
    private static _intance:XMLParser;
    public static getInstance():XMLParser
    {
        return this._intance ||= new XMLParser;
    }
    constructor()
    {

    }
    public parse(xmlString:string, pkgId:string=null):IXMLData
    {
        let s = this;
        if(!xmlString)return null;
        let parser = new DOMParser;
        let xml:any = parser.parseFromString(xmlString);           
        let node:any = xml.children[0];        
        let uiJSON:IXMLData = s.parseUI(node, pkgId);
        return uiJSON;
    }
    public parseUI(node:any, pkgId:string=null):IXMLData
    {
        let s = this;
        if(!node)return null;
        let tagDef:IXMLTag = XMLConfig.tag[node.nodeName];
        let attriDef:IXMLAttr;
        if(!tagDef)return null;
        let attris:any = node.attributes;        
        let displayData:IXMLData;
        if(pkgId == null)
        {
            let len:number = attris.length;
            while(--len>-1)
            {
                if(attris[len].localName == "id")
                {
                    pkgId = attris[len].value;
                    break;
                }
            }            
        }        
            
        displayData ||= {tagName:node.nodeName, pkgId:pkgId};
        //获取组件类名        
        displayData.cls = tagDef.cls;
        displayData.attrs = {};
        //获取组件属性
        let i:number,len:number,j:number,len2:number,k:number,len3:number;
        let attrName:string;
        let value:any;
        let values:string[];
        let ind:number;
        len = attris.length;
        for(i=0;i<len;++i)
        {
            attrName = attris[i].localName;               
            attriDef = XMLConfig.getAttrDef(displayData.tagName,attrName);
            if(!attriDef)continue;
            
            if(attriDef.names)
            {
                values = attris[i].value.split(",");
                len2 = attriDef.names.length;
                for(j=0;j<len2;++j)
                {
                    value = attriDef.type.strToValue(values[j]);
                    value = s.enumTrans(attriDef.enum, value);                                                     
                    displayData.attrs[attriDef.names[j]] = value;
                }
            }
            else
            {
                value = attriDef.type.strToValue(attris[i].value);     
                value = s.enumTrans(attriDef.enum, value);                                           
                displayData.attrs[attrName] = value;
            }            
        }
        //处理子级        
        len = node.children.length;
        if(len > 0)
        {
            let obj:any;
            displayData.childs = [];
            for(i=0;i<len;++i)
            {                
                obj = s.parseUI(node.children[i], pkgId);
                if(obj)
                    displayData.childs.push(obj);
            }
        }
        //处理tween            
        let tweenAttrDef:IXMLAttr;
        let valueKeys:string[];
        
        if(displayData.tagName == "transition" && displayData.childs)
        {
            valueKeys = ["value", "startValue", "endValue"];                                        
            let item:IXMLData;
            len = displayData.childs.length;
            for(i=0;i<len;++i)
            {
                item = displayData.childs[i];   
                tweenAttrDef = XMLConfig.getAttrDef("transition_item_type",item.attrs.type);
                if(tweenAttrDef == null)
                    continue;
                len3 = valueKeys.length;
                for(k=0;k<len3;++k)
                {
                    if(item.attrs[valueKeys[k]] == null)
                        continue;                    
                    value = item.attrs[valueKeys[k]];
                    value = tweenAttrDef.type.strToValue(value);
                    value = s.enumTrans(tweenAttrDef.enum, value);                
                    item.attrs[valueKeys[k]] = value;                     
                }                   
            }           
        }
        return displayData;
    }
    private enumTrans(enumArr:string[], value:any):number
    {
        let i:number, len:number, ind:number;        
        if(enumArr)
        {
            if(Array.isArray(value))
            {
                len = value.length;
                for(i=0;i<len;++i)
                {
                    ind = enumArr.indexOf(value[i]);
                    value[i] = ind;
                }
            }
            else
            {
                ind = enumArr.indexOf(value);
                value = (ind == -1?0:ind);
            }
        }
        
        return value;
    }
    /**根据标签名获取子级标签
     * @param data 标签数据
     * @param tagNames 标签名
     * @param recursion 是否递归子级，默认false
     * @param result 结果数组
    */
    public getTags(data:IXMLData,tagNames:string[], recursion:boolean=false, result:IXMLData[]=null):IXMLData[]
    {
        if(result == null)result = [];
        let childs:IXMLData[] = data.childs;
        let i:number,len:number;
        let s = this;
        if(childs)
        {
            len = childs.length;
            for(i=0;i<len;++i)
            {
                if(tagNames.indexOf(childs[i].tagName) > -1)
                    result.push(childs[i]);
                if(recursion)
                {
                    s.getTags(childs[i], tagNames, recursion, result);
                }
            }
        }            
        return result;
    }
    
}
